/******************************************************************************
 *                                                                            *
 *                        OS tasking body file                                *
 *                                                                            *
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*
 *              --- Included files and compilation variables ---              *
 *----------------------------------------------------------------------------*/

#include "OS_Cfg.h"

#include "OS_Task.h"

/*----------------------------------------------------------------------------*
 *                     --- Local constants & typedefs ---                     *
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*
 *                             --- Variables ---                              *
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*
 *                    --- Local functions declaration ---                     *
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*
 *                          --- Local functions ---                           *
 *----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*
 *                          --- Public functions ---                          *
 *----------------------------------------------------------------------------*/

/******************************************************************************
 * Function  : OS_ActivateTask
 *
 * Role      : Schedule a task for activation.
 *
 *-----------------------------------------------------------------------------
 * Entry     : Task ID enumerate
 *			   ExpirationTime of the task (0=immediate)
 *			   CyclicTime only in case of cyclic task, 0 for one shot task
 *  
 * Exit      : OS_NoError if succeed.
 *			   Can return OS_IdOutOfRange in debug.
 *  
 *-----------------------------------------------------------------------------
 * globals   : r/w Name Of Variable    Range       Description
 *             --- ------------------  ---------   ----------------------------
 *
 *
 ******************************************************************************/

OS_Error OS_ActivateTask(OS_TaskID TaskID, OS_TimeType ExpirationTime, OS_TimeType CyclicTime)
{
    OS_TaskType* const pTask = &OS_TaskArray[TaskID];

    
  	OS_DisableSysTick();
	if ( ExpirationTime==0 )
	{
        // Immediate scheduling
        pTask->Schedule++;
        OS_Control.TasksToSchedule++;
        // Next expiration after CyclicTime
        pTask->Expiration = CyclicTime;
	}
    else
    {
        // Delayed scheduling
        pTask->Expiration = ExpirationTime;
    }
    pTask->Reload = CyclicTime;
   	OS_EnableSysTick();

    return OS_NoError;
}


/******************************************************************************
 * Function  : OS_CancelTask
 *
 * Role      : Cancel a task
 *
 *-----------------------------------------------------------------------------
 * Entry     : Task ID enumerate
 *  
 * Exit      : OS_NoError in release. Can return OS_IdOutOfRange in debug.
 *  
 *-----------------------------------------------------------------------------
 * globals   : r/w Name Of Variable    Range       Description
 *             --- ------------------  ---------   ----------------------------
 *
 *
 ******************************************************************************/

OS_Error OS_CancelTask(OS_TaskID TaskID)
{
    OS_TaskType* const pTask = &OS_TaskArray[TaskID];

  	OS_DisableSysTick();
    pTask->Expiration = 0;
    pTask->Reload = 0;
	// Decrease total tasks to schedule counter
    OS_Control.TasksToSchedule-=pTask->Schedule;
    pTask->Schedule=0;
   	OS_EnableSysTick();

    return OS_NoError;
}

/******************************************************************************
 * Function  : OS_CancelAllTasks
 *
 * Role      : Cancel all tasks
 *
 *-----------------------------------------------------------------------------
 * Entry     : none
 *  
 * Exit      : none
 *  
 *-----------------------------------------------------------------------------
 * globals   : r/w Name Of Variable    Range       Description
 *             --- ------------------  ---------   ----------------------------
 *
 *
 ******************************************************************************/

void OS_CancelAllTasks(void)
{
	register OS_TaskType* pCtrlTask = &OS_TaskArray[0];

	OS_IndexType index;

   	OS_DisableSysTick();
	for (index=0; index<OS_MaxTask; index++)
	{
        pCtrlTask->Expiration = 0;
        pCtrlTask->Reload = 0;
		pCtrlTask++;
	}
	
	OS_Control.TasksToSchedule = 0;
   	OS_EnableSysTick();
}


/******************************************************************************
 * Function  : OS_IsTaskActive
 *
 * Role      : Return Task activity state for given task
 *
 *-----------------------------------------------------------------------------
 * Entry     : Task ID enumerate
 *  
 * Exit      : Task state
 *  
 *-----------------------------------------------------------------------------
 * globals   : r/w Name Of Variable    Range       Description
 *             --- ------------------  ---------   ----------------------------
 *
 *
 ******************************************************************************/

OS_BoolType OS_IsTaskActive(OS_TaskID TaskID)
{
    const OS_TaskType* const pTask = &OS_TaskArray[TaskID];
    
    return (OS_BoolType)((pTask->Expiration!=0)||(pTask->Reload!=0));
}


/******************************************************************************
 * Function  : OS_ScheduleTasks
 *
 * Role      : Schedule every in ready state. Must be call periodically by OS
 *
 *-----------------------------------------------------------------------------
 * Entry     : none
 *  
 * Exit      : none
 *  
 *-----------------------------------------------------------------------------
 * globals   : r/w Name Of Variable    Range       Description
 *             --- ------------------  ---------   ----------------------------
 *
 *
 ******************************************************************************/
#pragma CODE_SEG NON_BANKED

void OS_ScheduleTasks(void)
{
    OS_IndexType index=OS_MaxTask;
    OS_TaskType* pTask = OS_TaskArray;
    
    while ( (index!=0) && (OS_Control.TasksToSchedule!=0) )
    {
        if ( pTask->Schedule!=0 )
        {
            {
                // Decrease scheduler counters before executing task
            	OS_DisableSysTick();
                --pTask->Schedule;
                --OS_Control.TasksToSchedule;
    	        OS_EnableSysTick();
    	        // Otherwise, calling CancelTask within pTaskFct will corrupt OS_Control
                pTask->pTask();
            }
        }
        ++pTask;
        --index;
    }
}


/******************************************************************************
 * Function  : OS_TaskCheck
 *
 * Role      : Scan task array to check task scheduling coherency
 *
 *-----------------------------------------------------------------------------
 * Entry     : none
 *  
 * Exit      : none
 *  
 *-----------------------------------------------------------------------------
 * globals   : r/w Name Of Variable    Range       Description
 *             --- ------------------  ---------   ----------------------------
 *
 *
 ******************************************************************************/
void OS_TaskCheck(void)
{
	OS_IndexType index = OS_MaxTask;
	register OS_TaskType* pCtrlTask = &OS_TaskArray[0];
    OS_IndexType schedule=0;

    // Need to disable tick interrupt for calculation
   	OS_DisableSysTick();

    // Check every timer
    while ( index!=0 )
	{
        schedule += pCtrlTask->Schedule;
		    ++pCtrlTask;
        --index;
	}

    // Compare newly calculated activity with OS_Control    
    if ( schedule!=OS_Control.TasksToSchedule )
    {
        // No way to recover, timed events may have been lost.
        OS_SoftwareReset();
    }

    // Enable tick interrupt
   	OS_EnableSysTick();
}

#pragma CODE_SEG DEFAULT

/******************************************************************************
 *                               End of file                                  *
 ******************************************************************************/

